using Spine;
using System;
using UnityEngine;

[ExecuteInEditMode]
[AddComponentMenu("Spine/SkeletonUtilityBone")]
public class SkeletonUtilityBone : MonoBehaviour
{
	public enum Mode
	{
		Follow,
		Override
	}

	[NonSerialized]
	public bool valid;

	[NonSerialized]
	public SkeletonUtility skeletonUtility;

	[NonSerialized]
	public Bone bone;

	public Mode mode;

	public bool zPosition = true;

	public bool position;

	public bool rotation;

	public bool scale;

	public bool flip;

	public bool flipX;

	[Range(0f, 1f)]
	public float overrideAlpha = 1f;

	public string boneName;

	public Transform parentReference;

	[HideInInspector]
	public bool transformLerpComplete;

	protected Transform cachedTransform;

	protected Transform skeletonTransform;

	private bool nonUniformScaleWarning;

	public bool NonUniformScaleWarning => nonUniformScaleWarning;

	public void Reset()
	{
		bone = null;
		cachedTransform = base.transform;
		valid = (skeletonUtility != null && skeletonUtility.skeletonRenderer != null && skeletonUtility.skeletonRenderer.valid);
		if (valid)
		{
			skeletonTransform = skeletonUtility.transform;
			skeletonUtility.OnReset -= HandleOnReset;
			skeletonUtility.OnReset += HandleOnReset;
			DoUpdate();
		}
	}

	private void OnEnable()
	{
		skeletonUtility = SkeletonUtility.GetInParent<SkeletonUtility>(base.transform);
		if (!(skeletonUtility == null))
		{
			skeletonUtility.RegisterBone(this);
			skeletonUtility.OnReset += HandleOnReset;
		}
	}

	private void HandleOnReset()
	{
		Reset();
	}

	private void OnDisable()
	{
		if (skeletonUtility != null)
		{
			skeletonUtility.OnReset -= HandleOnReset;
			skeletonUtility.UnregisterBone(this);
		}
	}

	public void DoUpdate()
	{
		if (!valid)
		{
			Reset();
			return;
		}
		Skeleton skeleton = skeletonUtility.skeletonRenderer.skeleton;
		if (bone == null)
		{
			if (boneName == null || boneName.Length == 0)
			{
				return;
			}
			bone = skeleton.FindBone(boneName);
			if (bone == null)
			{
				UnityEngine.Debug.LogError("Bone not found: " + boneName, this);
				return;
			}
		}
		float num = (!(skeleton.flipX ^ skeleton.flipY)) ? 1f : (-1f);
		float num2 = 0f;
		if (flip && (flipX || flipX != bone.flipX) && bone.parent != null)
		{
			num2 = bone.parent.WorldRotation * -2f;
		}
		if (mode == Mode.Follow)
		{
			if (flip)
			{
				flipX = bone.flipX;
			}
			if (position)
			{
				cachedTransform.localPosition = new Vector3(bone.x, bone.y, 0f);
			}
			if (rotation)
			{
				if (bone.Data.InheritRotation)
				{
					if (bone.FlipX)
					{
						cachedTransform.localRotation = Quaternion.Euler(0f, 180f, bone.rotationIK - num2);
					}
					else
					{
						cachedTransform.localRotation = Quaternion.Euler(0f, 0f, bone.rotationIK);
					}
				}
				else
				{
					Vector3 eulerAngles = skeletonTransform.rotation.eulerAngles;
					Transform transform = cachedTransform;
					float x = eulerAngles.x;
					float y = eulerAngles.y;
					Vector3 eulerAngles2 = skeletonTransform.rotation.eulerAngles;
					transform.rotation = Quaternion.Euler(x, y, eulerAngles2.z + bone.worldRotation * num);
				}
			}
			if (scale)
			{
				cachedTransform.localScale = new Vector3(bone.scaleX, bone.scaleY, (!bone.worldFlipX) ? 1 : (-1));
				nonUniformScaleWarning = (bone.scaleX != bone.scaleY);
			}
		}
		else
		{
			if (mode != Mode.Override || transformLerpComplete)
			{
				return;
			}
			if (parentReference == null)
			{
				if (position)
				{
					Bone obj = bone;
					float x2 = bone.x;
					Vector3 localPosition = cachedTransform.localPosition;
					obj.x = Mathf.Lerp(x2, localPosition.x, overrideAlpha);
					Bone obj2 = bone;
					float y2 = bone.y;
					Vector3 localPosition2 = cachedTransform.localPosition;
					obj2.y = Mathf.Lerp(y2, localPosition2.y, overrideAlpha);
				}
				if (rotation)
				{
					float a = bone.Rotation;
					Vector3 eulerAngles3 = cachedTransform.localRotation.eulerAngles;
					float num3 = Mathf.LerpAngle(a, eulerAngles3.z, overrideAlpha) + num2;
					if (flip)
					{
						if (!flipX && bone.flipX)
						{
							num3 -= num2;
						}
						if (num3 >= 360f)
						{
							num3 -= 360f;
						}
						else if (num3 <= -360f)
						{
							num3 += 360f;
						}
					}
					bone.Rotation = num3;
					bone.RotationIK = num3;
				}
				if (scale)
				{
					Bone obj3 = bone;
					float scaleX = bone.scaleX;
					Vector3 localScale = cachedTransform.localScale;
					obj3.scaleX = Mathf.Lerp(scaleX, localScale.x, overrideAlpha);
					Bone obj4 = bone;
					float scaleY = bone.scaleY;
					Vector3 localScale2 = cachedTransform.localScale;
					obj4.scaleY = Mathf.Lerp(scaleY, localScale2.y, overrideAlpha);
					nonUniformScaleWarning = (bone.scaleX != bone.scaleY);
				}
				if (flip)
				{
					bone.flipX = flipX;
				}
			}
			else
			{
				if (transformLerpComplete)
				{
					return;
				}
				if (position)
				{
					Vector3 vector = parentReference.InverseTransformPoint(cachedTransform.position);
					bone.x = Mathf.Lerp(bone.x, vector.x, overrideAlpha);
					bone.y = Mathf.Lerp(bone.y, vector.y, overrideAlpha);
				}
				if (rotation)
				{
					float a2 = bone.Rotation;
					Vector3 eulerAngles4 = Quaternion.LookRotation((!flipX) ? Vector3.forward : (Vector3.forward * -1f), parentReference.InverseTransformDirection(cachedTransform.up)).eulerAngles;
					float num4 = Mathf.LerpAngle(a2, eulerAngles4.z, overrideAlpha) + num2;
					if (flip)
					{
						if (!flipX && bone.flipX)
						{
							num4 -= num2;
						}
						if (num4 >= 360f)
						{
							num4 -= 360f;
						}
						else if (num4 <= -360f)
						{
							num4 += 360f;
						}
					}
					bone.Rotation = num4;
					bone.RotationIK = num4;
				}
				if (scale)
				{
					Bone obj5 = bone;
					float scaleX2 = bone.scaleX;
					Vector3 localScale3 = cachedTransform.localScale;
					obj5.scaleX = Mathf.Lerp(scaleX2, localScale3.x, overrideAlpha);
					Bone obj6 = bone;
					float scaleY2 = bone.scaleY;
					Vector3 localScale4 = cachedTransform.localScale;
					obj6.scaleY = Mathf.Lerp(scaleY2, localScale4.y, overrideAlpha);
					nonUniformScaleWarning = (bone.scaleX != bone.scaleY);
				}
				if (flip)
				{
					bone.flipX = flipX;
				}
			}
			transformLerpComplete = true;
		}
	}

	public void FlipX(bool state)
	{
		if (state != flipX)
		{
			flipX = state;
			if (flipX)
			{
				Vector3 eulerAngles = base.transform.localRotation.eulerAngles;
				if (Mathf.Abs(eulerAngles.y) > 90f)
				{
					skeletonUtility.skeletonAnimation.LateUpdate();
					return;
				}
			}
			if (!flipX)
			{
				Vector3 eulerAngles2 = base.transform.localRotation.eulerAngles;
				if (Mathf.Abs(eulerAngles2.y) < 90f)
				{
					skeletonUtility.skeletonAnimation.LateUpdate();
					return;
				}
			}
		}
		bone.FlipX = state;
		base.transform.RotateAround(base.transform.position, skeletonUtility.transform.up, 180f);
		Vector3 eulerAngles3 = base.transform.localRotation.eulerAngles;
		eulerAngles3.x = 0f;
		eulerAngles3.y = (bone.FlipX ? 180 : 0);
		base.transform.localRotation = Quaternion.Euler(eulerAngles3);
	}

	public void AddBoundingBox(string skinName, string slotName, string attachmentName)
	{
		SkeletonUtility.AddBoundingBox(bone.skeleton, skinName, slotName, attachmentName, base.transform);
	}

	private void OnDrawGizmos()
	{
		if (NonUniformScaleWarning)
		{
			Gizmos.DrawIcon(base.transform.position + new Vector3(0f, 0.128f, 0f), "icon-warning");
		}
	}
}
